package com.bwie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsLog;
import com.bwie.pojo.TLog;
import com.bwie.service.TLogService;
import com.bwie.mapper.TLogMapper;
import com.bwie.utils.R;
import com.bwie.vo.LogPageVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
* @author Yoo19
* @description 针对表【t_log】的数据库操作Service实现
* @createDate 2025-05-05 18:25:51
*/
@Service
@Slf4j
public class TLogServiceImpl extends ServiceImpl<TLogMapper, TLog>
    implements TLogService{
    @Autowired
    TLogMapper tLogMapper;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 项目启动时，检查日志索引，如果索引不存在，创建索引
     */
    @PostConstruct
    public void readLogEs(){
        System.out.println("项目启动时，检查日志索引，如果索引不存在，创建索引");
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(EsLog.class);
        boolean exists = indexOperations.exists();
        if(!exists){
            System.out.println("索引不存在,创建索引");
            indexOperations.create();

            Document mapping = indexOperations.createMapping();
            indexOperations.putMapping(mapping);
        }
    }


    @KafkaListener(topics = "topic-log")
    public void  recvMessage(String Message, Acknowledgment acknowledgment){
        log.info("kafka接收到日志消息："+Message);
        //消费消息
        TLog tLog = JSON.parseObject(Message, TLog.class);
        tLogMapper.insert(tLog);

        //--把日志保存到ES中
        EsLog esLog = BeanUtil.toBean(tLog, EsLog.class);
        elasticsearchRestTemplate.save(esLog);



        //确认消息
        acknowledgment.acknowledge();

    }

    @Override
    public R getLogList(LogPageVo logPageVo) {
        //构造分页参数
        Integer pageNum = 0;
        if(logPageVo.getPageNum() != null && logPageVo.getPageNum()>0){
            pageNum = logPageVo.getPageNum() - 1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, logPageVo.getPageSize());
        //构造搜索条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //添加关键字查询
        if(StringUtils.isNotEmpty(logPageVo.getKeyWord())){
            boolQueryBuilder.should(
                    QueryBuilders.matchQuery("logContent",logPageVo.getKeyWord())
            );
        }
        //添加时间区间查询
        if(StringUtils.isNotEmpty(logPageVo.getBeginTime())){
            boolQueryBuilder.must(
                    QueryBuilders.rangeQuery("createTime")
                            .format("yyyy-MM-dd HH:mm:ss")
                            .timeZone("GMT+8")
                            .gte(logPageVo.getBeginTime())
            );
        }
        if(StringUtils.isNotEmpty(logPageVo.getEndTime())){
            boolQueryBuilder.must(
                    QueryBuilders.rangeQuery("createTime")
                            .format("yyyy-MM-dd HH:mm:ss")
                            .timeZone("GMT+8")
                            .lte(logPageVo.getEndTime())
            );
        }
        //添加精确查询
        if(logPageVo.getLogType() != null){
            boolQueryBuilder.must(
                    QueryBuilders.termQuery("logType",logPageVo.getLogType())
            );
        }

        //添加高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("logContent").preTags("<font color='red'>").postTags("</font>");

        //排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("createTime").order(SortOrder.DESC);


        //开始查询
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder
                .withPageable(pageRequest)
                .withSort(sortBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withQuery(boolQueryBuilder);
        SearchHits<EsLog> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsLog.class);

        //读取查询结果
        Long total = searchHits.getTotalHits();
        ArrayList<EsLog> records = new ArrayList<>();
        for (SearchHit<EsLog> searchHit : searchHits.getSearchHits()) {
            EsLog esLog = searchHit.getContent();

            //获取高亮结果
            List<String> logContentList = searchHit.getHighlightField("logContent");
            if(logContentList != null && logContentList.size()>0){
                String s = logContentList.get(0);
                esLog.setLogContent(s);
            }
            records.add(esLog);
        }

        //返回查询结果
        HashMap<String, Object> map = new HashMap<>();
        map.put("total",total);
        map.put("records",records);

        return R.OK(map);
    }
}




